package pl;

import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;

public class MasterFile extends DedicatedFile {

	private DedicatedFile[] dFs;
	private static byte j = 0;
	private final static byte dfSize = 4;
	private CardFile currentlySelected;

	public MasterFile(byte[] name, byte elementaryFileNumber)
	{
		//TODO: check ac cond for MF
		super(new byte[] {0x3F, 0x00}, name, elementaryFileNumber, new byte[]{ 0x06, 0x00, 0x00});
		dFs = new DedicatedFile[dfSize];
	}
	
	public CardFile findFile(byte[] fid)
	{
		if (fid[0] == 0x3F && fid[1] == 0x00) 
		{
			this.currentlySelected = this;
			return this;
		}
			
		// for all elementary file on global level
		if (super.findElementaryFile(fid) != null) 
		{
			this.currentlySelected = super.findElementaryFile(fid);
			return super.findElementaryFile(fid);
		}

		for (j = 0; j < dfSize; j++)
		{
			if (dFs[j] != null)
			{
				if (dFs[j].getFid()[0] == fid[0] && dFs[j].getFid()[1] == fid[1])
				{	
					this.currentlySelected = dFs[j];
					return dFs[j];
				}
				else
				{
					if (dFs[j].findElementaryFile(fid) != null) 
					{
						this.currentlySelected = dFs[j].findElementaryFile(fid);
						return dFs[j].findElementaryFile(fid);
					}
				}
			}
		}
		return null;
	}

	public void setCurrentlySelected(CardFile currentlySelected) {
		this.currentlySelected = currentlySelected;
	}
	
	public void setCurrentlySelected(byte[] fid) {
		
		currentlySelected = this;
		//TODO:
	}
	
	public CardFile getCurrentlySelected() {
		return currentlySelected;
	}
	
	// create file in the cardfilesystem
	public void createFile(byte[] fcpTemplate)
	{   
		// TODO: Optimize
		if (fci.parseFciTemplate(fcpTemplate))
		{
			if (findFile(fci.fidTlv.theValue) != null) ISOException.throwIt(ISO7816.SW_FILE_INVALID);

			if (this.currentlySelected instanceof MasterFile)
			{
				// global level -> creation EF || DF 
				if (fci.fdbTlv.theValue[0] == 0x38)
				{
					short slt;
					if ((slt = findFirstEmptySlotForDf()) != -1)
						
						if (findFile(fci.fidTlv.theValue) == null)
						dFs[slt] = 
							new DedicatedFile(
								fci.fidTlv.theValue, 
								fci.dfnameTlv.theValue, 
								(byte)8, 
								fci.accessTlv.theValue);
					else
						 ISOException.throwIt(ISO7816.SW_DATA_INVALID);
				}
				else
				{
					super.addElementaryFile(new ElementaryFile(
													fci.fidTlv.theValue, 
													fci.fdbTlv.theValue[0], 
													fci.filesizeTlv.theValue, 
													fci.accessTlv.theValue
												));				
				}
			}
			else if (this.currentlySelected instanceof DedicatedFile)
			{
				// df level -> only EF, DF not allowed
				if (fci.fdbTlv.theValue[0] == 0x38) 
					ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
				else
					((DedicatedFile)currentlySelected).addElementaryFile(new ElementaryFile(
							fci.fidTlv.theValue, 
							fci.fdbTlv.theValue[0], 
							fci.filesizeTlv.theValue, 
							fci.accessTlv.theValue
					)
					);		
			}
			else
				ISOException.throwIt(ISO7816.SW_COMMAND_NOT_ALLOWED);
		}
		else
			ISOException.throwIt(ISO7816.SW_DATA_INVALID);

	}
	
	public byte findFirstEmptySlotForDf()
	{
		for (short k = 0; k < dFs.length; k++)
		{
			if (dFs[k] == null)
			{
				return (byte) k;
			}
		}
		return -1;
	}
	
	public void readCurrentlySelectedEf(byte[] outBuff, short offset, short le)
	{
		if (getCurrentlySelected() != null 
				&& getCurrentlySelected() instanceof ElementaryFile)
			((ElementaryFile)getCurrentlySelected()).getFileContent(outBuff, offset, le);	
		else
			  ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
	}
	
	public byte[] readCurrentlySelectedEf(short offset, short le)
	{
		if (getCurrentlySelected() != null 
				&& getCurrentlySelected() instanceof ElementaryFile)
			return ((ElementaryFile)getCurrentlySelected()).getFileContent(offset, le);	
		else
			return null;
	}
	
	public void updateCurrentlySelectedEf(byte[] inBuff, short offset)
	{
		if (getCurrentlySelected() != null 
				&& getCurrentlySelected() instanceof ElementaryFile)
			((ElementaryFile)getCurrentlySelected()).setFileContent(inBuff, offset);
		else
			  ISOException.throwIt(ISO7816.SW_FILE_NOT_FOUND);
	}
	
}

